﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SmallJob.Data;
using SmallJob.Data.Interfaces;
using SmallJob.Model;
using SmallShop.Services.Interfaces;
using SmallJob.Services.Implements;

namespace SmallShop.Services.Implements
{
    public enum MessageType
    {
        User_User = 0, PROVIDE = 1, ORDER_PROVIDE = 2, REQUEST = 3, ORDER_REQUEST = 4    ,System_Notify=5  ,Message_Complaint=6
    }
    public class MessageService : RepositoryBase<Message>, IMessageService
    {
        public MessageService(IDatabaseFactory DbFactory) : base(DbFactory) { }
        public Message GetById(long Id)
        {
            return (from m in SmallJobDB.Messages
                    where m.ID == Id
                    select m).FirstOrDefault();
        }
        public List<Conversation> GetConversationById(int personId)
        {
            var lst = (from m in SmallJobDB.Messages
                       where m.SenderID == personId || m.ReceiveID == personId
                       select new
                                 {
                                     SenderID = m.SenderID,
                                     ReceiveID = m.ReceiveID,
                                     ProvideID = m.ProvideID,
                                     ID = m.ID,
                                     OrderID = m.OrderID,
                                     IsRead = m.IsRead,
                                     Type = m.Type,
                                     RequestID = m.RequestID,
                                     Date = m.Date
                                 }).ToList();
            var lstSendId = (from m in lst
                             where m.ReceiveID == personId
                             select m.SenderID).Distinct();
            var lstReceiveId = (from m in lst
                                where m.SenderID == personId
                                select m.ReceiveID).Distinct();
            var lstId = lstSendId.Concat(lstReceiveId).Distinct();
            List<Conversation> output = new List<Conversation>();
            foreach (var item in lstId)
            {
                Conversation c = new Conversation();
                //conversation 2 people
                var listAll = (from m in lst
                               where (m.SenderID == item && m.ReceiveID == personId) || (m.SenderID == personId && m.ReceiveID == item)
                               orderby m.Date descending
                               select new Message
                               {
                                   SenderID = m.SenderID,
                                   ReceiveID = m.ReceiveID,
                                   ProvideID = m.ProvideID,
                                   ID = m.ID,
                                   OrderID = m.OrderID,
                                   IsRead = m.IsRead,
                                   Date = m.Date,
                                   Type = m.Type,
                                   RequestID = m.RequestID
                               }).ToList();
                //conversation only private
                var mesUser2User = (from m in listAll
                                    where m.Type == (int)MessageType.User_User
                                    orderby m.Date descending
                                    select m).FirstOrDefault();
                if (mesUser2User != null)
                {
                    LoadContent(mesUser2User);
                    c.Message = mesUser2User;
                    output.Add(c);
                }
                //conversation about provide
                var lstAbtProvide = (from m in listAll
                                     where m.Type == (int)MessageType.PROVIDE
                                     select m).ToList();
                output.AddRange(SplitConversationProvide(lstAbtProvide));

                //conversation about request
                var lstAbtRequest = (from m in listAll
                                     where m.Type == (int)MessageType.REQUEST
                                     select m).ToList();
                output.AddRange(SplitConversationRequest(lstAbtRequest));
                //conversation about order
                //var lstAbtOrder = (from m in listAll
                //                   where m.OrderID != 0
                //                   select m).ToList();
                //output.AddRange(SplitConversationOrder(lstAbtOrder));
            }
            output = output.OrderByDescending(c => c.Message.Date).ToList();
            return output;
        }

        public int CountUnread(int userID)
        {
            return (from m in SmallJobDB.Messages
                    where m.ReceiveID == userID && !m.IsRead && (m.Type == (int)MessageType.User_User || m.Type == (int)MessageType.REQUEST || m.Type == (int)MessageType.PROVIDE)
                    select m).Count();
        }
        public int CountUnreadOrder(int userID)
        {
            return (from m in SmallJobDB.Messages
                    where m.ReceiveID == userID && !m.IsRead && m.OrderID != 0
                    select m).Count();
        }
        public void LoadContent(Message message)
        {
            if (message == null) return;
            if (string.IsNullOrWhiteSpace(message.Content))
            {
                message.Content = (from m in SmallJobDB.Messages
                                   where m.ID == message.ID
                                   select m.Content).SingleOrDefault();
            }

        }
        public void LoadConversation(Conversation conversation)
        {
            var id1 = conversation.Message.SenderID;
            var id2 = conversation.Message.ReceiveID;
            var tempmes = conversation.Message;
            var temp = (from m in SmallJobDB.Messages
                        where ((m.SenderID == id1 && m.ReceiveID == id2)
                        || (m.SenderID == id2 && m.ReceiveID == id1)) &&
                        m.OrderID == tempmes.OrderID &&
                        m.ProvideID == tempmes.ProvideID &&
                        m.RequestID == tempmes.RequestID &&
                        m.Type == tempmes.Type
                        orderby m.Date ascending
                        select m).ToList();

            conversation.Messages = temp;
        }
        public List<Conversation> SplitConversationProvide(List<Message> lstSource)
        {
            List<Conversation> output = new List<Conversation>();
            var listPvdId = (from m in lstSource
                             select m.ProvideID).Distinct();
            foreach (var item in listPvdId)
            {
                var lastM = (from m in lstSource
                             where m.ProvideID == item
                             orderby m.Date descending
                             select m).FirstOrDefault();
                var tempC = new Conversation();
                if (lastM != null)
                {
                    LoadContent(lastM);
                    tempC.Message = lastM;
                    output.Add(tempC);
                }

            }
            return output;
        }
        public List<Conversation> SplitConversationRequest(List<Message> lstSource)
        {
            List<Conversation> output = new List<Conversation>();
            var listPvdId = (from m in lstSource
                             select m.RequestID).Distinct();
            foreach (var item in listPvdId)
            {
                var lastM = (from m in lstSource
                             where m.RequestID == item
                             orderby m.Date descending
                             select m).FirstOrDefault();
                var tempC = new Conversation();
                if (lastM != null)
                {
                    LoadContent(lastM);
                    tempC.Message = lastM;
                    output.Add(tempC);
                }

            }
            return output;
        }
        public List<Conversation> SplitConversationOrder(List<Message> lstSource)
        {
            List<Conversation> output = new List<Conversation>();
            var listOrdId = (from m in lstSource
                             select m.OrderID).Distinct();
            foreach (var item in listOrdId)
            {
                var lastM = (from m in lstSource
                             where m.OrderID == item
                             orderby m.Date descending
                             select m).FirstOrDefault();
                var tempC = new Conversation();
                if (lastM != null)
                {
                    LoadContent(lastM);
                    tempC.Message = lastM;
                    output.Add(tempC);
                }

            }
            return output;
        }
        public Conversation GetConversationByOrderId(int orderid)
        {
            var result = from m in SmallJobDB.Messages
                         where m.OrderID == orderid
                         orderby m.Date ascending
                         select m;
            var cvs = new Conversation();
            cvs.Messages = result.ToList();
            cvs.Message = result.FirstOrDefault();
            return cvs;
        }

        public List<Conversation> GetConversationOrderById(int personId)
        {
            var list = (from m in SmallJobDB.Messages
                        join o in SmallJobDB.Orders on m.OrderID equals o.ID
                        where (m.SenderID == personId || m.ReceiveID == personId) &&
                        (m.Type == (int)MessageType.ORDER_PROVIDE || m.Type == (int)MessageType.ORDER_REQUEST) &&
                        (!o.Completed || o.Comment == null || o.Comment.Length <= 0) &&
                        !o.IsDeleted
                        select m).ToList();
            List<Conversation> output = new List<Conversation>();
            output.AddRange(SplitConversationOrder(list));
            output = output.OrderByDescending(c => c.Message.Date).ToList();
            return output;
        }
    }
}
